/**create by liuhua at 2019年6月11日 上午11:13:25**/
package com.star.truffle.module.fzjz.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import com.star.truffle.common.constants.EnabledEnum;
import com.star.truffle.common.importdata.AbstractDataImport;
import com.star.truffle.common.importdata.FieldValue;
import com.star.truffle.common.importdata.ImportResult;
import com.star.truffle.common.importdata.RecordType;
import com.star.truffle.core.StarServiceException;
import com.star.truffle.core.security.dto.StarUserInfo;
import com.star.truffle.core.util.DateUtils;
import com.star.truffle.module.fzjz.cache.PictureInfoCache;
import com.star.truffle.module.fzjz.cache.WarCategoryCache;
import com.star.truffle.module.fzjz.cache.WarInfoCache;
import com.star.truffle.module.fzjz.constant.PictureBusinessEnum;
import com.star.truffle.module.fzjz.domain.FzjzUserInfo;
import com.star.truffle.module.fzjz.domain.PictureInfo;
import com.star.truffle.module.fzjz.dto.req.WarCategoryRequestDto;
import com.star.truffle.module.fzjz.dto.req.WarInfoRequestDto;
import com.star.truffle.module.fzjz.dto.res.WarCategoryResponseDto;

public class ImportWarInfo extends AbstractDataImport<WarInfoRequestDto> {

  private WarInfoCache warInfoCache;
  private WarCategoryCache warCategoryCache;
  private PictureInfoCache pictureInfoCache;
  
  public ImportWarInfo(byte[] bs, String filename) {
    super(bs, filename);
  }

  @Override
  public List<RecordType> getRecordTypes() {
    List<RecordType> types = Collections.synchronizedList(new ArrayList<>());
    types.add(new RecordType("pictureNames", String.class, "文本", true));
    types.add(new RecordType("lng", String.class, "文本"));
    types.add(new RecordType("lat", String.class, "文本"));
    types.add(new RecordType("zoom", String.class, Integer.class, "数字", "{\"1\":1,\"2\":2,\"3\":3,\"4\":4,\"5\":5,\"6\":6,\"7\":7,\"8\":8,\"9\":9,\"10\":10,\"11\":11,\"12\":12,\"13\":13,\"14\":14,\"15\":15,\"16\":16,\"17\":17,\"18\":18}"));
    types.add(new RecordType("stations", String.class, "文本"));
    Object cId = getParams().get("cateId");
    Long cateId = null == cId ? 0L : Long.parseLong(cId.toString());
    WarCategoryResponseDto cate = warCategoryCache.getWarCategory(cateId);
    if(null != cate) {
      List<String> fields = cate.getFields();
      if(null != fields && ! fields.isEmpty()) {
        fields.stream().forEach(field -> {
          types.add(new RecordType(field, String.class, "文本", true));
        });
      }
    }
    return types;
  }

  @Override
  public Class<WarInfoRequestDto> getBeanType() {
    return WarInfoRequestDto.class;
  }

  public void save(ImportResult importResult) {
    List<List<FieldValue>> successList = importResult.getSuccessRecords();
    if (null == successList || successList.isEmpty()) {
      return;
    }
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    StarUserInfo starUserInfo = null;
    Integer areaId = 0;
    if (null != auth) {
      starUserInfo = (StarUserInfo) auth.getPrincipal();
      FzjzUserInfo info = (FzjzUserInfo) starUserInfo.getUserInfos().get(0).getUserInfo();
      areaId = info.getAreaId();
    }
    List<List<FieldValue>> errorList = importResult.getErrorRecords();
    List<WarInfoRequestDto> data = new ArrayList<>();
    for (List<FieldValue> record : successList) {
      WarInfoRequestDto dto = new WarInfoRequestDto();
      record.stream().filter(rec -> rec.getFieldName().equals("lat")).findAny().ifPresent(rec -> dto.setLat(null != rec.getValue() ? rec.getValue().toString() : ""));
      record.stream().filter(rec -> rec.getFieldName().equals("lng")).findAny().ifPresent(rec -> dto.setLng(null != rec.getValue() ? rec.getValue().toString() : ""));
      record.stream().filter(rec -> rec.getFieldName().equals("pictureNames")).findAny().ifPresent(rec -> dto.setPictureNames(null != rec.getValue() ? rec.getValue().toString() : ""));
      record.stream().filter(rec -> rec.getFieldName().equals("zoom")).findAny().ifPresent(rec -> dto.setZoom(Integer.parseInt(rec.getValue().toString())));
      record.stream().filter(rec -> rec.getFieldName().equals("stations")).findAny().ifPresent(rec -> {
        Object value = rec.getValue();
        if(null != value) {
          dto.setStations(Arrays.asList(value.toString().split("[,，]")).stream().map(str -> str.strip()).distinct().collect(Collectors.toList()));
        }
      });
      dto.setAreaId(areaId);
      Map<String, Object> line = new HashMap<>();
      for (FieldValue fieldValue : record) {
        if(fieldValue.getFieldName().equals("lat") || fieldValue.getFieldName().equals("lng") || fieldValue.getFieldName().equals("pictureNames")) {
          continue;
        }
        line.put(fieldValue.getFieldName(), fieldValue.getValue());
      }
      dto.setInfos(line);
      data.add(dto);
    }
    Map<Integer, Object> errorIdx = saveBean(importResult.getSheetName(), data);
    List<List<FieldValue>> removed = new ArrayList<>();
    if (null != errorIdx && !errorIdx.isEmpty()) {
      for (Map.Entry<Integer, Object> en : errorIdx.entrySet()) {
        int idx = en.getKey();
        Object value = en.getValue();
        List<FieldValue> list = successList.get(idx);
        removed.add(list);

        if (value instanceof Integer) {
          int index = (Integer) value;
          FieldValue fieldValue = list.get(index);
          fieldValue.toError(fieldValue.getCaption() + "信息未找到");
        } else if (value instanceof String) {
          FieldValue fieldValue = new FieldValue();
          fieldValue.setRowNum(idx);
          fieldValue.toError("异常", (String) value);
          list.add(fieldValue);
        }
        errorList.add(list);
      }
      for (List<FieldValue> list : removed) {
        successList.remove(list);
      }
      errorList.sort((a, b) -> {
        int ar = a.get(0).getRowNum();
        int br = b.get(0).getRowNum();
        return Integer.compare(ar, br);
      });
    }
  }
  
  @Override
  public Map<Integer, Object> saveBean(String sheetName, List<WarInfoRequestDto> list) {
    WarCategoryRequestDto warCategoryRequestDto = new WarCategoryRequestDto();
    warCategoryRequestDto.setName(sheetName);
    Map<Integer, Object> errorIdx = new LinkedHashMap<>();
    List<WarCategoryResponseDto> cates = warCategoryCache.queryWarCategory(warCategoryRequestDto);
    Object cateId = getParams().get("cateId");
    if(null == cateId) {
      throw new StarServiceException("参数错误，请联系管理员！cateId不能为空");
    }else if(null == cates || cates.isEmpty()) {
      throw new StarServiceException("图层不存在(Excel工作表的sheetName)");
    }else {
      Long cid = cates.get(0).getCateId();
      if(! cid.equals(Long.valueOf(cateId.toString()))) {
        throw new StarServiceException("选择导入的图层与Excel内的图层不一致");
      }else {
        StarUserInfo user = (StarUserInfo) this.getParams().get("loginUser");
        Date now = new Date();
        if(null != list && ! list.isEmpty()) {
          list.stream().forEach(warInfo -> {
            warInfo.setCreateTime(now);
            warInfo.setCateId(cid);
            warInfo.setCreateUser(user.getUsername());
            warInfo.setUpdateTime(warInfo.getCreateTime());
            warInfo.setUpdateUser(warInfo.getCreateUser());
            warInfo.setEnabled(EnabledEnum.enabled.val());
          });
          warInfoCache.batchSaveWarInfo(list);
          List<PictureInfo> pictures = list.stream().filter(warInfo -> StringUtils.isNotBlank(warInfo.getPictureNames())).flatMap(warInfo -> {
            String names = warInfo.getPictureNames();
            return Stream.of(names.split("[,，]")).map(name -> {
              PictureInfo info = new PictureInfo();
              info.setBusiness(PictureBusinessEnum.zzt.getBusiness());
              info.setBusinessId(warInfo.getId());
              info.setUrl("/photo/image/" + DateUtils.formatNow("yyMMdd") + "/" + name);
              return info;
            });
          }).collect(Collectors.toList());
          pictureInfoCache.batchSavePicture(pictures);
        }
      }
    }
    return errorIdx;
  }

  @Override
  public void getApplication(ApplicationContext applicationContext) {
    warInfoCache = applicationContext.getBean(WarInfoCache.class);
    warCategoryCache = applicationContext.getBean(WarCategoryCache.class);
    pictureInfoCache = applicationContext.getBean(PictureInfoCache.class);
  }
}
